# -*- coding=utf-8 -*-

from flask import current_app
from flask_security import UserMixin, RoleMixin, utils
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired
# from passlib.apps import custom_app_context as pwd_context
from sqlalchemy.ext.hybrid import hybrid_property
import time, random, string

from src.utils.models import db
from src.utils.serializing import Serializer


class RolesUsers(db.Model):
    __tablename__ = 'sys_roles_users'
    id = db.Column(db.Integer(), primary_key=True)
    user_id = db.Column('user_id', db.Integer(), db.ForeignKey('sys_user.id'))
    role_id = db.Column('role_id', db.Integer(), db.ForeignKey('sys_role.id'))


class Role(db.Model, RoleMixin):
    __tablename__ = 'sys_role'
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))


class User(db.Model, UserMixin):
    __tablename__ = 'sys_user'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    username = db.Column(db.String(255))
    thumbnail = db.Column(db.String(100), nullable=True)
    password = db.Column(db.String(255))
    #
    last_login_at = db.Column(db.DateTime())
    current_login_at = db.Column(db.DateTime())
    last_login_ip = db.Column(db.String(100))
    current_login_ip = db.Column(db.String(100))
    login_count = db.Column(db.Integer)
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary='sys_roles_users',
                            backref=db.backref('users', lazy='dynamic'))

    def __repr__(self):
        return '%r %r' % (self.username, self.email)

    def set_password(self, pwd):
        self.password = utils.hash_password(pwd)
        db.session.commit()

    def verify_password(self, password):
        return utils.verify_hash(self.password, password)

    def change_admin(self):
        admin = Role.query.filter(Role.name == 'admin').first()
        if admin in self.roles:
            self.roles.remove(admin)
        else:
            self.roles.append(admin)

    def is_admin(self):
        roles = [each.name for each in self.roles]
        if 'admin' in roles:
            return True
        return False

    def get_auth_code(self):
        s = Serializer(current_app)
        token = s.serialize_data([str(self.id)])
        code = s.get_code()
        return code, token

    def verify_auth_token(self, token):
        try:
            data = Serializer(current_app).deserialize_data(token)
        except SignatureExpired:
            return None  # valid token, but expired
        except BadSignature:
            return None  # invalid token
        return data['email'] == self.email

    def get_setup(self):
        return dict(key=self.id, username=self.username,
                    email=self.email, admin=self.is_admin(), thumbnail=self.thumbnail)

    @hybrid_property
    def authentication_token(self):
        return self.generate_auth_token()

    @hybrid_property
    def name(self):
        if self.user_profile and self.user_profile.first_name:
            if self.user_profile.last_name:
                return self.user_profile.first_name + self.user_profile.last_name
            return self.user_profile.first_name


class Position(db.Model, UserMixin):
    __tablename__ = 'sys_position'
    id = db.Column(db.String(50), primary_key=True,
                   default=str(int(time.time() * 1000)) + ''.join(
                       random.sample(string.ascii_letters + string.digits, 20)))
    pid = db.Column(db.String(50))
    code = db.Column(db.String(255), unique=True)
    code_ios2 = db.Column(db.String(100), nullable=True)
    code_ios3 = db.Column(db.String(100), nullable=True)
    name_cn = db.Column(db.String(255))
    name_cn_short = db.Column(db.String(255))
    name_en_short = db.Column(db.String(255))
    description = db.Column(db.String(255))
    status = db.Column(db.Integer, nullable=False)  # '状态；1-正常；0-无效',

    created_time = db.Column(db.BigInteger, nullable=False, default=int(time.time() * 1000))
    created_user_id = db.Column(
        db.Integer, db.ForeignKey('sys_user.id'))
    updated_time = db.Column(
        db.BigInteger, nullable=False, default=int(time.time() * 1000))
    updated_user_id = db.Column(
        db.Integer, db.ForeignKey('sys_user.id'))


class Currency(db.Model, UserMixin):
    """
    @tableName:sys_currency
    @chinese:货币
    """
    __tablename__ = 'sys_currency'
    id = db.Column(db.String(50), primary_key=True,
                   default=str(int(time.time() * 1000)) + ''.join(
                       random.sample(string.ascii_letters + string.digits, 20)))
    code_ios = db.Column(db.String(20), nullable=True)
    name_full = db.Column(db.String(255))
    name_cn = db.Column(db.String(255))
    sig = db.Column(db.String(255))
    description = db.Column(db.String(255))
    status = db.Column(db.Integer, nullable=False)  # '状态；1-正常；0-无效',

    created_time = db.Column(db.BigInteger, nullable=False, default=int(time.time() * 1000))
    created_user_id = db.Column(
        db.Integer, db.ForeignKey('sys_user.id'))
    updated_time = db.Column(
        db.BigInteger, nullable=False, default=int(time.time() * 1000))
    updated_user_id = db.Column(
        db.Integer, db.ForeignKey('sys_user.id'))


class Corporate(db.Model):
    """
    @tableName:pay_currency
    @chinese:法人，个人
    """
    __tablename__ = 'sys_currency'
    id = db.Column(db.String(30), primary_key=True, default=str(int(time.time() * 1000)) + ''.join(
        random.sample(string.ascii_letters + string.digits, 20)))
    code = db.Column(db.String(30))  #
    name = db.Column(db.String(25), nullable=False)
    description = db.Column(db.String(25), nullable=False)
    type = db.Column(db.String(20), nullable=False)  # person,company,SEO
    status = db.Column(db.Integer, nullable=False)  # '账务状态；1-正常；0-无效',
    validity_period_start = db.Column(
        db.BigInteger, nullable=False, default=time.time() * 1000000)
    validity_period_end = db.Column(
        db.BigInteger, nullable=False, default=4102376399)

    created_time = db.Column(db.BigInteger, nullable=False, default=int(time.time() * 1000))
    created_user_id = db.Column(
        db.Integer, db.ForeignKey('sys_user.id'))
    updated_time = db.Column(
        db.BigInteger, nullable=False, default=int(time.time() * 1000))
    updated_user_id = db.Column(
        db.Integer, db.ForeignKey('sys_user.id'))

    def __init__(self, name, description=None):
        self.name = name
        self.description = description

    def __repr__(self):
        return '<Currency %r>' % self.name
